use axum::extract::{Path, Query};
use axum::Form;
use axum::{extract::State, Json};

use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

use crate::stores::sql;
use crate::{services, SharedState};

#[derive(Deserialize)]
pub struct LeaveMessageParam {
    pub fromopenid: String,
    pub toopenid: String,
    pub message: String,
}
pub async fn leave_message(
    State(state): State<SharedState>,
    Form(params): Form<LeaveMessageParam>,
) -> Json<Value> {
    let fromopenid = params.fromopenid;
    let toopenid = params.toopenid;
    let message = params.message;
    let pool = &state.db;
    let cnt = services::user::get_user_count(&pool, fromopenid.clone())
        .await
        .unwrap();
    if cnt == 0 {
        return Json(json!({"code":-1,"msg":"参数错误"}));
    }
    let cnt = services::user::get_user_count(&pool, toopenid.clone())
        .await
        .unwrap();
    if cnt == 0 {
        return Json(json!({"code":-1,"msg":"参数错误"}));
    }

    if let Err(e) = sql::leave_message(&pool, fromopenid, toopenid, message).await {
        tracing::error!("leave_message err, {}", e);
        return Json(json!({"code":-1,"msg":"留言失败"}));
    }
    Json(json!({"code":1,"msg":"留言成功"}))
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Paging {
    pub page: i32,
    pub page_size: i32,
}
pub async fn get_pub_book_list(
    State(state): State<SharedState>,
    Query(paging): Query<Paging>,
) -> Json<Value> {
    let pool = &state.db;
    if let Ok(recs) = sql::get_pub_book_list(pool, paging.page, paging.page_size).await {
        tracing::debug!("get_pub_book_list {:?}", recs);
        let dj = serde_json::to_string(&recs).unwrap();
        return Json(json!({"code":1,"msg":"获取成功","data":dj}));
    }
    Json(json!({"code":-1,"msg":"获取失败"}))
}

#[derive(Debug, Serialize, Deserialize)]
pub struct IdPageParam {
    pub openid: String,
    pub page: i32,
    pub page_size: i32,
}
pub async fn get_my_book_list(
    State(state): State<SharedState>,
    Query(param): Query<IdPageParam>,
) -> Json<Value> {
    let pool = &state.db;
    if let Ok(recs) = sql::get_my_book_list(&pool, param.openid, param.page, param.page_size).await
    {
        tracing::debug!("get_my_book_list {:?}", recs);
        let dj = serde_json::to_string(&recs).unwrap();
        return Json(json!({"code":1,"msg":"获取成功","data":dj}));
    }
    Json(json!({"code":-1,"msg":"获取失败"}))
}

pub async fn get_leavetomsg_list(
    State(state): State<SharedState>,
    Query(param): Query<IdPageParam>,
) -> Json<Value> {
    let pool = &state.db;
    if let Ok(recs) = sql::get_mp_tomsg_list(pool, param.openid, param.page, param.page_size).await
    {
        tracing::debug!("get_leavetomsg_list {:?}", recs);
        let dj = serde_json::to_string(&recs).unwrap();
        return Json(json!({"code":1,"msg":"获取成功","data":dj}));
    }

    Json(json!({"code":-1,"msg":"获取失败"}))
}

#[derive(Debug, Deserialize)]
pub struct AddBookParam {
    pub openid: String,
    pub name: String,
    pub press: String,
    pub isbn: String,
}

pub async fn add_mybook(
    State(state): State<SharedState>,
    Form(params): Form<AddBookParam>,
) -> Json<Value> {
    let openid = params.openid;
    let name = params.name;
    let press = params.press;
    let isbn = params.isbn;
    let pool = &state.db;
    let cnt = services::user::get_user_count(&pool, openid.clone())
        .await
        .unwrap();
    if cnt == 0 {
        return Json(json!({"code":-1,"msg":"参数错误"}));
    }

    let bc = sql::query_book_count_v1(&pool, openid.clone(), isbn.clone()).await;

    match bc {
        Ok(cnt) => {
            if cnt > 0 {
                return Json(json!({"code":-1,"msg":"图书已经存在"}));
            } else {
                if let Err(e) = sql::add_book(&pool, openid, name, press, isbn, 0).await {
                    tracing::error!("add_book err, {}", e);
                    return Json(json!({"code":-1,"msg":"添加失败"}));
                }
            }
        }
        Err(e) => {
            tracing::error!("query_book_count_v1 err, {}", e);
            return Json(json!({"code":-1,"msg":"系统错误"}));
        }
    }

    Json(json!({"code":1,"msg":"添加成功"}))
}

pub async fn share_mybook(
    State(state): State<SharedState>,
    Path(param): Path<(String, i64)>,
) -> Json<Value> {
    let openid = param.0;
    let id = param.1;
    let pool = &state.db;
    let cnt = services::user::get_user_count(&pool, openid.clone())
        .await
        .unwrap();
    if cnt == 0 {
        return Json(json!({"code":-1,"msg":"参数错误"}));
    }

    if let Err(e) = sql::share_book_by_id(&pool, openid, id).await {
        tracing::error!("share_book_by_id err, {}", e);
        return Json(json!({"code":-1,"msg":"分享失败"}));
    }

    Json(json!({"code":1,"msg":"分享成功"}))
}

pub async fn delete_mybook(
    State(state): State<SharedState>,
    Path(param): Path<(String, i64)>,
) -> Json<Value> {
    let openid = param.0;
    let id = param.1;
    let pool = &state.db;
    let cnt = services::user::get_user_count(&pool, openid.clone())
        .await
        .unwrap();
    if cnt == 0 {
        return Json(json!({"code":-1,"msg":"参数错误"}));
    }

    if let Err(e) = sql::delete_book_by_id(&pool, openid, id).await {
        tracing::error!("delete_book_by_id err, {}", e);
        return Json(json!({"code":-1,"msg":"删除失败"}));
    }

    Json(json!({"code":1,"msg":"删除成功"}))
}

pub async fn delete_leavemsg(
    State(state): State<SharedState>,
    Path(openid): Path<String>,
    Path(id): Path<i64>,
) -> Json<Value> {
    let pool = &state.db;
    let cnt = services::user::get_user_count(&pool, openid.clone())
        .await
        .unwrap();
    if cnt == 0 {
        return Json(json!({"code":-1,"msg":"参数错误"}));
    }

    if let Err(e) = sql::delete_leavemsg_by_id(&pool, openid, id).await {
        tracing::error!("delete_leavemsg_by_id err, {}", e);
        return Json(json!({"code":-1,"msg":"删除失败"}));
    }

    Json(json!({"code":1,"msg":"删除成功"}))
}
